package thread;

import java.util.Random;

/**
 * <p>Title:ThreadLocalTest</p>
 * <p>Description:ThreadLocal实现线程范围的共享变量</p>
 * @author	xiongfei
 * @date	2017年6月6日 下午4:38:05
 * @version 1.0
 */

public class ThreadLocalTest {
	/**
	 * ThreadLocal类及应用技巧 
	 * 将线程范围内共享数据进行封装，封装到一个单独的数据类中，提供设置获取方法 
	 * 将该类单例化，提供获取实例对象的方法，获取到的实例对象是已经封装好的当前
	 * 线程范围内的对象 
	 */
	public static void main(String[] args) {
		for (int i = 0; i < 2; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					int data = new Random().nextInt();
					MyThreadLocal.getThreadInstance().setId(data);
					new A().get();
					new B().get();
				}
			}).start();
		}
	}

	static class A {
		public void get() {
			// 可以直接使用获取到的线程范围内的对象实例调用相应方法
			MyThreadLocal data = MyThreadLocal.getThreadInstance();
			System.out.println("A from thread " + Thread.currentThread().getName() + " id:"
			        + data.getId());
		}
	}

	static class B {
		public void get() {

			// 可以直接使用获取到的线程范围内的对象实例调用相应方法
			MyThreadLocal data = MyThreadLocal.getThreadInstance();
			System.out.println("B from thread " + Thread.currentThread().getName() + " id:"
			        + data.getId());

		}
	}

}

class MyThreadLocal {
	// 单例
	private MyThreadLocal() {};

	// 将实例对象存入当前线程范围内数据集中
	private static ThreadLocal<MyThreadLocal> map = new ThreadLocal<MyThreadLocal>();

	// 提供获取实例方法
	public static MyThreadLocal getThreadInstance() {
		// 从当前线程范围内数据集中获取实例对象
		MyThreadLocal myThreadLocal = map.get();
		if (null == myThreadLocal) {
			myThreadLocal = new MyThreadLocal();
			map.set(myThreadLocal);
		}
		return myThreadLocal;
	}

	private int id;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		System.out.println(Thread.currentThread().getName() + " put id=" + id);
		this.id = id;
	}

}
